package com.shenyutao.customimagecrop.new_

import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import com.shenyutao.customimagecrop.R

/**
 * @author ShenYuTao
 */
class CustomImageViewCrop : View {
    private lateinit var mBitmap: Bitmap
    private var mMatrix = Matrix()
    private val mBitmapPaint = Paint()
    private val mClipRectPaint = Paint()

    private val mInitialCoordination = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)
    private var mChangeableCoordination = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)

    /**
     * 裁剪框尺寸
     */
    private var mClipRectLeft: Float = 0f
    private var mClipRectTop: Float = 0f
    private var mClipRectRight: Float = 0f
    private var mClipRectBottom: Float = 0f

    /**
     * 裁剪框当前移动量
     */
    private var translateX = 0f
    private var translateY = 0f

    /**
     * bitmap当前的旋转角度
     */
    private var mRealBitMapRotate = 0f

    /**
     * 一次旋转的角跨度
     */
    private val mRotateDegree = 90f

    /**
     * 裁剪框当前旋转角度
     */
    private var mRealClipRectRotate = 0f

    /**
     * 裁剪框当前的缩放程度，用于伴随旋转动画的缩放动画
     */
    private var mRealClipRectScale = 1f

    /**
     * 通过手势控制的裁剪框缩放程度
     */
    private var mRealClipRectScaleByGesture = 1f
    private val mErasePaint = Paint(Paint.ANTI_ALIAS_FLAG)

    /**
     * 缩放手势监听
     */
    private var beforeScaleFactor = 1f
    private val scaleGestureDetector =
        ScaleGestureDetector(context, object : ScaleGestureDetector.OnScaleGestureListener {
            override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean {
                beforeScaleFactor = detector!!.scaleFactor
                return true
            }

            override fun onScale(detector: ScaleGestureDetector?): Boolean {
                if (detector!!.scaleFactor < 1f) {
                    val spacing = beforeScaleFactor - detector.scaleFactor
                    beforeScaleFactor = detector.scaleFactor
                    if (mRealClipRectScaleByGesture > 0.3f) {
                        mRealClipRectScaleByGesture -= spacing
                    }
                }

                if (detector.scaleFactor > 1f) {
                    val spacing = detector.scaleFactor - beforeScaleFactor
                    beforeScaleFactor = detector.scaleFactor
                    if (mRealClipRectScaleByGesture < 2f) {
                        mRealClipRectScaleByGesture += spacing
                    }
                }

                invalidate()
                return false
            }

            override fun onScaleEnd(detector: ScaleGestureDetector?) {

            }

        })

    /**
     * 普通手势监听
     */
    private val gestureDetector =
        GestureDetector(context, object : GestureDetector.OnGestureListener {
            override fun onDown(e: MotionEvent?): Boolean {
                Log.i("Test", "onDown: ")
                return false
            }

            override fun onShowPress(e: MotionEvent?) {
            }

            override fun onSingleTapUp(e: MotionEvent?): Boolean {
                return true
            }

            override fun onScroll(
                e1: MotionEvent?,
                e2: MotionEvent?,
                distanceX: Float,
                distanceY: Float
            ): Boolean {
                translateX -= distanceX
                translateY -= distanceY
                invalidate()
                Log.i("Test", "onScroll: $distanceY  $distanceX")
                return true
            }

            override fun onLongPress(e: MotionEvent?) {
                return
            }

            override fun onFling(
                e1: MotionEvent?,
                e2: MotionEvent?,
                velocityX: Float,
                velocityY: Float
            ): Boolean {
                return true
            }

        })


    constructor(context: Context) : super(context) {
        init(null, 0)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(attrs, 0)
    }

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(
        context,
        attrs,
        defStyle
    ) {
        init(attrs, defStyle)
    }

    private fun init(attrs: AttributeSet?, defStyle: Int) {
        // 设置bitmap画笔
        mBitmapPaint.isAntiAlias = true
        mBitmapPaint.isFilterBitmap = true

        // 设置裁剪框画笔
        mClipRectPaint.isAntiAlias = true
        mClipRectPaint.style = Paint.Style.STROKE
    }

    private fun initInitialCoordination() {
        mInitialCoordination[0] = 0f
        mInitialCoordination[1] = 0f
        mInitialCoordination[2] = mBitmap.width * 1f
        mInitialCoordination[3] = 0f
        mInitialCoordination[4] = mBitmap.width * 1f
        mInitialCoordination[5] = mBitmap.height * 1f
        mInitialCoordination[6] = 0f
        mInitialCoordination[7] = mBitmap.height * 1f

    }

    private fun initChangeableCoordination() {
        mChangeableCoordination = floatArrayOf(
            mInitialCoordination[0],
            mInitialCoordination[1],
            mInitialCoordination[2],
            mInitialCoordination[3],
            mInitialCoordination[4],
            mInitialCoordination[5],
            mInitialCoordination[6],
            mInitialCoordination[7],
        )
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        mBitmap = createBitmap()


//        mClipRectLeft = width / 8f
//        mClipRectTop = height / 32f
//        mClipRectRight = mClipRectLeft + mBitmap.width / 1f
//        mClipRectBottom = mClipRectTop + mBitmap.height / 2f

        initInitialCoordination()
        initChangeableCoordination()

    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.save()
        canvas.translate(width / 8f, height / 32f)
        canvas.drawBitmap(mBitmap, mMatrix, mBitmapPaint)
        canvas.restore()
        //绘制裁剪框

        drawClipRect(canvas)
    }

    private fun createBitmap(): Bitmap {
        val loadBitmap = BitmapFactory.decodeResource(resources, R.drawable.image)
        val scaleProportion = width * 1f / loadBitmap.width / 4f * 3f
        val adjustMatrix = Matrix()
        adjustMatrix.setScale(scaleProportion, scaleProportion)
        return Bitmap.createBitmap(
            loadBitmap,
            0,
            0,
            loadBitmap.width,
            loadBitmap.height,
            adjustMatrix,
            true
        )
    }

    private fun drawClipRect(
        canvas: Canvas
    ) {
        //获取经过mMatrix处理后四个点的坐标
        initChangeableCoordination()
        mMatrix.mapPoints(mChangeableCoordination)
        // 创建一个新的layer
        canvas.saveLayer(0f, 0f, width * 1f, height * 1f, null)
        canvas.translate(width / 8f, height / 32f)
        // 设置裁剪框区域
        val path = Path()
        path.moveTo(mChangeableCoordination[0], mChangeableCoordination[1])
        path.lineTo(mChangeableCoordination[2], mChangeableCoordination[3])
        path.lineTo(mChangeableCoordination[4], mChangeableCoordination[5])
        path.lineTo(mChangeableCoordination[6], mChangeableCoordination[7])
        path.close()
        // 设置canvas
        canvas.drawARGB(100, 0, 0, 0)
        // 设置画笔的XFermode，当设置为PorterDuff.Mode.CLEAR时，画笔绘制的区域alpha和color都为0，相当于橡皮檫
        mErasePaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
        mErasePaint.color = Color.GREEN
        mErasePaint.style = Paint.Style.FILL

        canvas.drawPoint(mChangeableCoordination[0], mChangeableCoordination[1], mErasePaint)
        canvas.drawPoint(mChangeableCoordination[2], mChangeableCoordination[3], mErasePaint)
        canvas.drawPoint(mChangeableCoordination[4], mChangeableCoordination[5], mErasePaint)
        canvas.drawPoint(mChangeableCoordination[6], mChangeableCoordination[7], mErasePaint)
        // 绘制裁剪框区域
        canvas.drawPath(path, mErasePaint)

//        mClipRectPaint.strokeWidth = 10f
//        mClipRectPaint.color = Color.WHITE
//        mClipRectPaint.style = Paint.Style.STROKE
//        canvas.drawRect(rect, mClipRectPaint)


//        drawClipRectCorner(canvas)
//        drawClipRectGuideLine(canvas)


        // 还原canvas状态至未进行旋转缩放的状态
        canvas.restore()
    }

    private fun drawClipRectCorner(canvas: Canvas) {
        val length = mBitmap.width * 1f / 16
        mClipRectPaint.strokeWidth = 15f
        mClipRectPaint.color = Color.WHITE
        mClipRectPaint.strokeCap = Paint.Cap.ROUND

        //左上角
        canvas.drawLine(
            mClipRectLeft,
            mClipRectTop,
            mClipRectLeft + length,
            mClipRectTop,
            mClipRectPaint
        )
        canvas.drawLine(
            mClipRectLeft,
            mClipRectTop,
            mClipRectLeft,
            mClipRectTop + length,
            mClipRectPaint
        )

        //右上角
        canvas.drawLine(
            mClipRectRight,
            mClipRectTop,
            mClipRectRight - length,
            mClipRectTop,
            mClipRectPaint
        )
        canvas.drawLine(
            mClipRectRight,
            mClipRectTop,
            mClipRectRight,
            mClipRectTop + length,
            mClipRectPaint
        )

        //左下角
        canvas.drawLine(
            mClipRectLeft,
            mClipRectBottom,
            mClipRectLeft,
            mClipRectBottom - length,
            mClipRectPaint
        )
        canvas.drawLine(
            mClipRectLeft,
            mClipRectBottom,
            mClipRectLeft + length,
            mClipRectBottom,
            mClipRectPaint
        )

        //右下角
        canvas.drawLine(
            mClipRectRight,
            mClipRectBottom,
            mClipRectRight - length,
            mClipRectBottom,
            mClipRectPaint
        )
        canvas.drawLine(
            mClipRectRight,
            mClipRectBottom,
            mClipRectRight,
            mClipRectBottom - length,
            mClipRectPaint
        )

    }

    private fun drawClipRectGuideLine(canvas: Canvas) {
        mClipRectPaint.strokeWidth = 1f
        mClipRectPaint.color = Color.WHITE
        mClipRectPaint.strokeCap = Paint.Cap.BUTT

        //线间距
        val clipRectHeight = mClipRectBottom - mClipRectTop
        val clipRectWidth = mClipRectRight - mClipRectLeft
        val verticalLineSpacing = clipRectWidth / 3
        val horizontalLineSpacing = clipRectHeight / 3

        //画竖直的两条辅助线
        canvas.drawLine(
            mClipRectLeft + verticalLineSpacing,
            mClipRectTop,
            mClipRectLeft + verticalLineSpacing,
            mClipRectBottom,
            mClipRectPaint
        )
        canvas.drawLine(
            mClipRectLeft + verticalLineSpacing * 2,
            mClipRectTop,
            mClipRectLeft + verticalLineSpacing * 2,
            mClipRectBottom,
            mClipRectPaint
        )

        //画水平的两条辅助线
        canvas.drawLine(
            mClipRectLeft,
            mClipRectTop + horizontalLineSpacing,
            mClipRectRight,
            mClipRectTop + horizontalLineSpacing,
            mClipRectPaint
        )
        canvas.drawLine(
            mClipRectLeft,
            mClipRectTop + horizontalLineSpacing * 2,
            mClipRectRight,
            mClipRectTop + horizontalLineSpacing * 2,
            mClipRectPaint
        )
    }

    fun rotateBitmapWithScale() {
        //缩放比例
        val scaleProportion = (width * 1.0f - height * 1f / 16) / mBitmap.height

        //旋转动画，set操作会覆盖掉之前的所有操作，包括scale操作
        val rotateAnimator =
            ValueAnimator.ofFloat(mRealBitMapRotate, mRealBitMapRotate + mRotateDegree)
        rotateAnimator.addUpdateListener {
            mMatrix.setRotate(it.animatedValue as Float, mBitmap.width / 2f, mBitmap.height / 2f)
            mRealClipRectRotate = it.animatedValue as Float
            invalidate()
        }

        //缩放动画
        val scaleAnimator = if (mRealBitMapRotate == 0f || mRealBitMapRotate == 180f) {
            ValueAnimator.ofFloat(1f, scaleProportion)
        } else {
            ValueAnimator.ofFloat(scaleProportion, 1f)
        }

        //post在之前操作的基础上进行操作
        scaleAnimator.addUpdateListener {
            mMatrix.postScale(
                it.animatedValue as Float,
                it.animatedValue as Float,
                mBitmap.width / 2f,
                mBitmap.height / 2f
            )
            mRealClipRectScale = it.animatedValue as Float
            invalidate()
        }


        //一边旋转一边缩放
        val animatorSet = AnimatorSet()
        animatorSet.play(rotateAnimator).with(scaleAnimator)
        animatorSet.start()

        //记录当前旋转角
        mRealBitMapRotate += 90f
        mRealBitMapRotate %= 360f
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        scaleGestureDetector.onTouchEvent(event)
        gestureDetector.onTouchEvent(event)
        return true
    }


}